package util

import (
	"fmt"
	"github.com/go-playground/validator/v10"
	"reflect"
	"strconv"
)

// MaxLen 不许字符串长度大于设定值
var MaxLen validator.Func = func(fl validator.FieldLevel) bool {
	vlen := len(fl.Field().String())
	param := fl.Param()
	if param == "" {
		panic("maxLen format: maxLen=1")
	}
	v, err := strconv.Atoi(param)
	if err != nil {
		panic("maxLen:" + err.Error())
	}
	if vlen <= v {
		return true
	}
	panic(fmt.Sprintf("长度不能大于%d", v))
}

// MinLen 不许字符串长度小于设定值
var MinLen validator.Func = func(fl validator.FieldLevel) bool {
	vlen := len(fl.Field().String())
	param := fl.Param()
	if param == "" {
		panic("minLen format: maxLen=1")
	}
	v, err := strconv.Atoi(param)
	if err != nil {
		panic("minLen:" + err.Error())
	}
	if vlen >= v {
		return true
	}
	panic(fmt.Sprintf("长度不能小于%d", v))
}

// Max 不许数值大于设定值
var Max validator.Func = func(fl validator.FieldLevel) bool {
	reqValue := reflect.ValueOf(fl.Field().Interface())
	var num int
	switch reqValue.Kind() {
	case reflect.Int:
		num = fl.Field().Interface().(int)
	case reflect.String:
		num, _ = strconv.Atoi(fl.Field().Interface().(string))
	}
	param := fl.Param()
	v, err := strconv.Atoi(param)
	if err != nil {
		panic("maxLen:" + err.Error())
	}
	if num <= v {
		return true
	}
	panic(fmt.Sprintf("数值不能大于%d", v))
}

// Min 不许数值小于设定值
var Min validator.Func = func(fl validator.FieldLevel) bool {
	reqValue := reflect.ValueOf(fl.Field().Interface())
	var num int
	switch reqValue.Kind() {
	case reflect.Int:
		num = fl.Field().Interface().(int)
	case reflect.String:
		num, _ = strconv.Atoi(fl.Field().Interface().(string))
	}
	param := fl.Param()
	v, err := strconv.Atoi(param)
	if err != nil {
		panic("maxLen:" + err.Error())
	}
	if num >= v {
		return true
	}
	panic(fmt.Sprintf("数值不能小于%d", v))
}

// CheckRank 排序数据校验器
var CheckRank validator.Func = func(fl validator.FieldLevel) bool {
	//这里因为前端请求参数有时候用string有时候又是int，而且go貌似不支持int和string的自动转换，所以我用反射解决这个问题。
	v := reflect.ValueOf(fl.Field().Interface())
	var count int
	switch v.Kind() {
	case reflect.Invalid:
		panic("未知类型")
	case reflect.String:
		count, _ = strconv.Atoi(fl.Field().Interface().(string))
	default:
		count = fl.Field().Interface().(int)
	}
	if count >= 1 && count <= 200 {
		return true
	}
	panic("数值必须为1-200区间")
}

// CheckLevel 分类等级校验器
var CheckLevel validator.Func = func(fl validator.FieldLevel) bool {
	count := fl.Field().Interface().(int)
	if count >= 1 && count <= 3 {
		return true
	}
	panic("数值必须为1-3区间")
}
